package com.corp.common.base.wrapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.collections4.CollectionUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分页对象封装
 *
 * @author yf
 */
@ApiModel(value = "分页", description = "分页视图")
@Setter
@Getter
@NoArgsConstructor
@ToString
public class Pagination<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 总记录数
     */
    @ApiModelProperty(value = "总条数")
    private long total;
    /**
     * 当前页数
     */
    @ApiModelProperty(value = "页码")
    private long pageNo;
    /**
     * 每页记录数
     */
    @ApiModelProperty(value = "每页显示条数")
    private long pageSize;
    /**
     * 总页数
     */
    @ApiModelProperty(value = "总页数")
    private long totalPage;

    /**
     * 列表数据
     */
    @ApiModelProperty(value = "列表数据")
    private List<T> records;

    /**
     * 分页
     *
     * @param records  列表数据
     * @param total    总记录数
     * @param pageSize 每页记录数
     * @param pageNo   当前页数
     */
    public Pagination(List<T> records, long total, long pageNo, long pageSize) {
        this.records = records;
        this.total = total;
        this.pageNo = pageNo;
        this.pageSize = pageSize;
        this.totalPage = (long) Math.ceil((double) total / pageSize);
    }


    /**
     * 分页
     */
    public Pagination(IPage<T> page) {
        this.records = page.getRecords();
        this.total = page.getTotal();
        this.pageNo = page.getCurrent();
        this.pageSize = page.getSize();
        this.totalPage = page.getPages();
    }


    public static <T> Pagination<T> of(List<T> records, long total, long pageNo, long pageSize) {
        final Pagination<T> pagination = new Pagination<>();
        pagination.records = records;
        pagination.total = total;
        pagination.pageNo = pageNo;
        pagination.pageSize = pageSize;
        pagination.totalPage = (long) Math.ceil((double) total / pageSize);
        return pagination;
    }

    public static <T> Pagination<T> of(Collection<T> records, long total, long pageNo, long pageSize) {
        final Pagination<T> pagination = new Pagination<>();
        pagination.records = new ArrayList<>(records);
        pagination.total = total;
        pagination.pageNo = pageNo;
        pagination.pageSize = pageSize;
        pagination.totalPage = (long) Math.ceil((double) total / pageSize);
        return pagination;
    }


    public static <T> Pagination<T> of(IPage<T> page) {
        final Pagination<T> pagination = new Pagination<>();
        pagination.records = page.getRecords();
        pagination.total = page.getTotal();
        pagination.pageNo = page.getCurrent();
        pagination.pageSize = page.getSize();
        pagination.totalPage = page.getPages();
        return pagination;
    }

    public static <T,R> Pagination<R> of(IPage<T> page, Function<T,R> function){
        final Pagination<R> pagination = new Pagination<>();
        pagination.total = page.getTotal();
        pagination.pageNo = page.getCurrent();
        pagination.pageSize = page.getSize();
        pagination.totalPage = page.getPages();
        if(CollectionUtils.isNotEmpty(page.getRecords())){
            pagination.records = page.getRecords().stream().map(function).collect(Collectors.toList());
        }else{
            pagination.records = new ArrayList<>();
        }
        return pagination;
    }
}
